/*
    YmsgIRC - Program enabling YMSG chat clients to use IRC
    Copyright (C) 2011 Crash Daemonicus ( crashenator -at- gmail.com )

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "YMSG_field.h"


YmsgField::YmsgField(){  num=-1;processed=false; assembled=false;compound=false; }




YmsgField::YmsgField(const string& s){
    //dbg_head("YmsgField::YmsgField(string s)"); 
   // dbgline(s);
    num=-1;
    value="";
    str=s;
    processed=false;
    assembled=true;
    compound=false;
    process();
    //dbg_foot(0);
}
YmsgField::YmsgField(const string& s,const bool bProcess){
    //dbg_head("YmsgField::YmsgField(string s,bool bProcess)"); 
    //dbgline(s);
    num=-1;
    value="";
    str=s;
    processed=false;
    assembled=true;
    compound=false;
    if(bProcess) process();
    //dbg_foot(0);
}
//str=newstr(c);num=0;value=0;processed=false;
//if(bProcess) process();

YmsgField::YmsgField(const int i,const string& s, const bool bAssemble){ 
    //dbg_head("YmsgField::YmsgField(int i,string s,bool bAssemble)");
    //dbg_do(printf("%d=%s\n",i,s.c_str()));
    num=i;
    value=s;
    str="";
    processed=true;
    assembled=false;
    compound=false;
    if(bAssemble){ assemble(); dbgline(str); }
    
   // dbg_foot(0);
}
YmsgField::YmsgField(const int i,const int v)
{
    num=i;
    value=itos(v);
    str="";
    processed=true;
    assembled=false;
    compound=false;
	assemble();
}




void YmsgField::process(){
    dbg_head ("YmsgField::process()");
    if(compound) { dbg_foot("cantProcCompound");return;}
    if(processed) { dbg_foot("alreadyproc");return;}
    num=-1;
    value="";
    if(!assembled) { dbg_foot("notAssembled");return;}
    
    
    processed=true;
    valid=false;
    string s1,s2;
    s1=string(str);
    s2="\xC0\x80";
    size_t found=s1.find(s2);
    if(found==-1){ dbg_foot("del1notfound");return;}
    num=atoi(s1.substr(0,found).c_str());
    s1.erase(0,found+2);//erase the FieldNum+Delim
    found=s1.find(s2);//find the delim ending the FieldData
    if(found==-1){ dbg_foot("del2notfound");return;}// why here? unterminated FieldData is invalid.
    value=s1.substr(0,found);
    valid=true;
    dbg_foot("valid");
}
void YmsgField::assemble(){
    dbg_head("YmsgField::assemble()");
    if(assembled) { dbg_foot("alreadyassembled");return;}
    if(compound) { dbgline("Warning: assemble() overwriting compound field.");}
    str="";
    if(!processed){dbg_foot("notprocessed");return;}
    
    //char buf[10];
    //itoa(num,buf,10);
    str=itos(num)+"\xC0\x80"+value+"\xC0\x80";
    assembled=true;
    dbg_foot(0);
}


const YmsgField& YmsgField::operator=(const string& s){
    dbg_head("YmsgField& YmsgField::operator=(const string& s)"); 
    str=s;//even though s is byref, this is still a deep copy
    num=-1;
    value="";
    processed=false;
    assembled=true;
    compound=false;
    process();
    ReturnD(*this);
}


const YmsgField& YmsgField::operator+=(const YmsgField& f2)
{   
    dbg_head("YmsgField::operator+=(const YmsgField& f2)");
    if(!assembled) assemble();
    //if(!f2.assembled) f2.assemble();//can't assemble Const f2
    if(assembled && f2.assembled){
        dbgline(str);
        dbgline(f2.str);
        str+=f2.str;
        processed=false;
        compound=true;
        dbgline(str);
    }else{
        dbgline("notasembled");
    }
    ReturnD(*this);
}


bool YmsgField::operator==(const YmsgField& f2) const
{  
    dbg_head("YmsgField::operator==(const YmsgField& f2)");
    if(assembled && f2.assembled){
        ReturnD(str==f2.str);
    }else if(processed && f2.processed){
		if(  num!=f2.num  ) ReturnD(false);
		if(value!=f2.value) ReturnD(false);
		ReturnD(true);
	}else{

        ReturnX(false,"notassembled && notprocessed");
    }
}


vector<YmsgField> YmsgField::operator+(const YmsgField& f2)
{
	vector<YmsgField> fields;
	fields.push_back(*this);
	fields.push_back(f2);
	return fields;
}
vector<YmsgField> YmsgField::operator+(vector<YmsgField> fields2)
{
	vector<YmsgField> fields;
	fields.push_back(*this);
	fields.insert(fields.end(),fields2.begin(),fields2.end());
	return fields;
}


string YmsgField::toString()
{
	if(!assembled) assemble();
	return str;
}


void YmsgField::debug() const
{
	dbg_head("YmsgField");
	dbgline(itos(num).c_str());
	dbgline(value.c_str());
	dbgline(str.c_str());
	dbg_foot(0);
}